/*
 * Copyright (C) 2011, EADS France
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */
package xowl.interpreter.backends.rete;

import java.util.Collection;
import java.util.Iterator;

/**
 *
 * @author Laurent WOUTERS
 */
public class NestedLoopJoin extends JoinStrategy implements Iterator<Couple> {
    private Collection<Token> tokens;
    private Iterator<TripleFact> iterFacts;
    private Iterator<Token> iterTokens;
    private TripleFact nextFact;
    private Couple nextCouple = null;
    
    public NestedLoopJoin(BetaJoinNodeTest t1, BetaJoinNodeTest t2, BetaJoinNodeTest t3) {
        super(t1, t2, t3);
    }
    
    @Override public Iterator<Couple> join(Collection<Token> tokens, Collection<TripleFact> facts) {
        this.tokens = tokens;
        this.iterFacts = facts.iterator();
        this.iterTokens = tokens.iterator();
        this.nextFact = this.iterFacts.next();
        this.nextCouple = findNext();
        return this;
    }
    
    @Override public boolean hasNext() { return (nextCouple != null); }
    @Override public Couple next() {
        Couple result = nextCouple;
        nextCouple = findNext();
        return result;
    }
    @Override public void remove() { }
    
    private Couple findNext() {
        while (iterTokens != null) {
            Token currentToken = iterTokens.next();
            TripleFact currentFact = nextFact;
            // Advance iterators
            if (!iterTokens.hasNext()) {
                // no more tokens => go to next fact
                if (!iterFacts.hasNext()) {
                    // no more facts => set token iterator to null
                    iterTokens = null;
                } else {
                    // go to next fact and reset token iterator
                    nextFact = iterFacts.next();
                    iterTokens = tokens.iterator();
                }
            }
            // test values
            if (passTests(currentToken, currentFact))
                return new Couple(currentFact, currentToken);
        }
        return null;
    }
}
